﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.Administration;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Diagnostics;
using Microsoft.SharePoint.Deployment;
using Microsoft.SharePoint.Utilities;
using System.Reflection;
using Microsoft.SharePoint.Administration;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint.WebControls;
using System.Web;

namespace Macaw.Moss2007.ContentChangesOverviewSolution
{
    public class ChangesOverviewTree : Microsoft.SharePoint.WebControls.LayoutsPageBase
    {

        protected SPTreeView tvChanges;
        protected ChangeTypesMenuButton menuChangeTypes;
        protected ObjectTypesMenuButton menuObjecTypes;
        protected CDPathMenuButton menuCDPath;
        protected StartTimeMenuButton menuStarttime;

        protected override void OnLoad(EventArgs e)
        {
            if (!IsPostBack)
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    Populate();
                });
            }


            base.OnLoad(e);
        }

        private void Populate()
        {
            using (SPSite site = new SPSite(SPContext.Current.Site.ID))
            {
                SPChangeQuery query = new SPChangeQuery(true, true);

                if (!menuCDPath.CDPath.Equals(Guid.Empty))
                {
                    ContentDeploymentPath cdpath = ContentDeploymentPath.GetInstance(menuCDPath.CDPath);

                    foreach (DeploymentStatus status in cdpath.DeploymentStatusDictionary.Values)
                    {
                        if (status.ObjectType == SPDeploymentObjectType.Site && site.ID.Equals(status.Id))
                        {
                            SPChangeToken changetoken = new SPChangeToken(status.LastExportChangeToken);
                            query.ChangeTokenStart = changetoken;
                        }
                    }
                }

                if (menuStarttime.Ago != StartTimeMenuButton.EnumAgo.All)
                {
                    DateTime agotime = DateTime.MinValue;
                    switch (menuStarttime.Ago)
                    {
                        case StartTimeMenuButton.EnumAgo.OneDayAgo:
                            agotime = DateTime.UtcNow.AddDays(-1);
                            break;
                        case StartTimeMenuButton.EnumAgo.OneHourAgo:
                            agotime = DateTime.UtcNow.AddHours(-1);
                            break;
                        case StartTimeMenuButton.EnumAgo.OneMonthAgo:
                            agotime = DateTime.UtcNow.AddMonths(-1);
                            break;
                        case StartTimeMenuButton.EnumAgo.OneWeekAgo:
                            agotime = DateTime.UtcNow.AddDays(-7);
                            break;
                        case StartTimeMenuButton.EnumAgo.TwoWeeksAgo:
                            agotime = DateTime.UtcNow.AddDays(-14);
                            break;

                    }
                    query.ChangeTokenStart = new SPChangeToken(SPChangeCollection.CollectionScope.Site, site.ID, agotime);
                }



                query.Alert = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Alert) != 0;
                query.ContentType = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.ContentType) != 0;
                query.Field = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Field) != 0;
                query.File = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.File) != 0;
                query.Folder = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Folder) != 0;
                query.Group = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Group) != 0;
                query.Item = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Item) != 0;
                query.List = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.List) != 0;
                query.Navigation = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Navigation) != 0;
                query.SecurityPolicy = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.SecurityPolicy) != 0;
                query.Site = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Site) != 0;
                query.User = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.User) != 0;
                query.View = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.View) != 0;
                query.Web = (menuObjecTypes.CheckedMenuItemIds & ObjectTypesMenuButton.enumObjectTypes.Web) != 0;


                query.Add = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.Add) != 0;
                query.Delete = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.Delete) != 0;
                query.Move = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.Move) != 0;
                query.Navigation = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.Navigation) != 0;
                query.GroupMembershipAdd = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.GroupMembershipAdd) != 0;
                query.GroupMembershipDelete = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.GroupMembershipDelete) != 0;
                query.RoleAssignmentAdd = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.RoleAssignmentAdd) != 0;
                query.RoleAssignmentDelete = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.RoleAssignmentDelete) != 0;
                query.RoleDefinitionAdd = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.RoleDefinitionAdd) != 0;
                query.RoleDefinitionDelete = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.RoleDefinitionDelete) != 0;
                query.RoleDefinitionUpdate = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.RoleDefinitionUpdate) != 0;
                query.Rename = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.Rename) != 0;
                query.Restore = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.Restore) != 0;
                query.SystemUpdate = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.SystemUpdate) != 0;
                query.Update = (menuChangeTypes.CheckedMenuItemIds & ChangeTypesMenuButton.enumChangeTypes.Update) != 0;

                tvChanges.Nodes.Clear();

                System.Web.Caching.Cache cache = HttpContext.Current.Cache;
                SPChangeCollection changes = null;
                do
                {
                    try
                    {
                        changes = site.GetChanges(query);
                    }
                    catch
                    {
                        // An error may occur if the ChangeTokenStart is a time prior to the start of the ChangeLog. Fix it, by quering all.
                        if (query.ChangeTokenStart != null)
                        {
                            query.ChangeTokenStart = null;
                            changes = site.GetChanges(query);
                        }
                    }


                    if (changes != null && changes.Count > 0)
                    {
                        foreach (SPChange change in changes)
                        {
                            using (SPSite csite = new SPSite(change.SiteId))
                            {
                                string key = string.Format("change_{0}", change.ChangeToken.ToString());
                                RetrievedChangeInfo changeinfo = (RetrievedChangeInfo)cache.Get(key);
                                if (changeinfo == null)
                                {
                                    changeinfo = SPChangeHelper.GetChangeInfo(change, csite);
                                    cache.Add(key, changeinfo, null, DateTime.MaxValue, new TimeSpan(0, 10, 0), System.Web.Caching.CacheItemPriority.Low, null);
                                }
                                if (!string.IsNullOrEmpty(changeinfo.objectUrl))
                                {
                                    TreeNode pathnode = tvChanges.FindNode(changeinfo.objectUrl);
                                    if (pathnode == null)
                                    { // Path does not exist yet.
                                        System.Diagnostics.Debug.WriteLine("Not found: '" + changeinfo.objectUrl + "'");
                                        string[] pathparts = changeinfo.objectUrl.Split(new char[] { '/' });
                                        string path = "";
                                        TreeNode parentnode = null;
                                        int idx = 0;
                                        foreach (string pathpart in pathparts)
                                        {
                                            if (idx > 0) path += tvChanges.PathSeparator;
                                            idx++;
                                            path += pathpart;
                                            System.Diagnostics.Debug.WriteLine("Finding node: '" + path + "'");
                                            pathnode = tvChanges.FindNode(path);
                                            if (pathnode == null)
                                            {
                                                string text = pathpart;
                                                if (string.IsNullOrEmpty(text)) text = "/";
                                                pathnode = new TreeNode(text, pathpart);

                                                pathnode.NavigateUrl = changeinfo.objectUrl;
                                                if (parentnode != null)
                                                {
                                                    parentnode.ChildNodes.Add(pathnode);
                                                }
                                                else
                                                {
                                                    tvChanges.Nodes.Add(pathnode);
                                                }
                                            }
                                            parentnode = pathnode;
                                        }
                                        pathnode.ToolTip = string.Join(" ", new string[] { pathnode.ToolTip, change.ChangeType.ToString() });
                                    }
                                    else
                                    { // Node already exist. Multiple changes on the same item
                                        pathnode.ToolTip = string.Join(" ", new string[] { pathnode.ToolTip, change.ChangeType.ToString() });
                                    }
                                }
                            }
                        }
                    }
                    query.ChangeTokenStart = changes.LastChangeToken;
                } while (changes.Count == SPChangeCollection.CountLimit);
            };
        }


        /// <summary>
        /// Click event handler of Refresh-button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void btnRefresh_Click(object sender, EventArgs e)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                Populate();
            });
        }

    }
}
